<?php

declare(strict_types=1);

namespace App\Models;

use Str;

/**
 * Class Comment
 *
 * @property int                             $id                主键id
 * @property int                             $socialite_user_id 评论用户id
 * @property int                             $type              1：文章评论
 * @property int                             $pid               父级id
 * @property int                             $article_id        文章id
 * @property string                          $content           内容
 * @property int                             $is_audited        是否已审核
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property \Illuminate\Support\Carbon|null $deleted_at
 * @property-read \App\Models\Article $article
 * @property-read \App\Models\SocialiteUser $socialiteUser
 *
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Base disableCache()
 * @method static \GeneaLabs\LaravelModelCaching\CachedBuilder|\App\Models\Comment newModelQuery()
 * @method static \GeneaLabs\LaravelModelCaching\CachedBuilder|\App\Models\Comment newQuery()
 * @method static \GeneaLabs\LaravelModelCaching\CachedBuilder|\App\Models\Comment query()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment whereArticleId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment whereContent($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment whereDeletedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment whereIsAudited($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment wherePid($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment whereSocialiteUserId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment whereType($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Comment whereUpdatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Base withCacheCooldownSeconds($seconds = null)
 * @mixin \Eloquent
 */
class Comment extends Base
{
    // 用于递归
    private $child = [];

    public function getContentAttribute($value)
    {
        return $this->ubbToImage($value);
    }

    public function setContentAttribute($value)
    {
        $this->attributes['content'] = $this->imageToUbb($value);
    }

    public function article()
    {
        return $this->belongsTo(Article::class)->withDefault();
    }

    public function socialiteUser()
    {
        return $this->belongsTo(SocialiteUser::class)->withDefault();
    }

    public function ubbToImage($content)
    {
        $ubb   = ['[Kiss]', '[Love]', '[Yeah]', '[啊！]', '[背扭]', '[顶]', '[抖胸]', '[88]', '[汗]', '[瞌睡]', '[鲁拉]', '[拍砖]', '[揉脸]', '[生日快乐]', '[摊手]', '[睡觉]', '[瘫坐]', '[无聊]', '[星星闪]', '[旋转]', '[也不行]', '[郁闷]', '[正Music]', '[抓墙]', '[撞墙至死]', '[歪头]', '[戳眼]', '[飘过]', '[互相拍砖]', '[砍死你]', '[扔桌子]', '[少林寺]', '[什么？]', '[转头]', '[我爱牛奶]', '[我踢]', '[摇晃]', '[晕厥]', '[在笼子里]', '[震荡]'];
        $count = count($ubb);
        $image = [];

        // 循环生成img标签
        for ($i = 1; $i <= $count; $i++) {
            $image[] = '<img src="' . asset('statics/emote/tuzki/' . $i . '.gif') . '" title="' . str_replace(['[', ']'], '', $ubb[$i - 1]) . '" alt="' . config('app.name') . '">';
        }

        return str_replace($ubb, $image, $content);
    }

    public function imageToUbb($content)
    {
        $content = html_entity_decode(htmlspecialchars_decode($content));
        // 删标签 去空格 转义
        $content = strip_tags(trim($content), '<img>');
        preg_match_all('/<img.*?title="(.*?)".*?>/i', $content, $img);
        $search  = $img[0];
        $replace = array_map(function ($v) {
            return '[' . $v . ']';
        }, $img[1]);
        $content = str_replace($search, $replace, $content);

        return clean(strip_tags($content));
    }

    public function getDataByArticleId($article_id)
    {
        // 关联第三方用户表获取一级评论
        $data = $this->select('comments.*', 'ou.name', 'ou.avatar', 'ou.is_admin')
            ->join('socialite_users as ou', 'comments.socialite_user_id', 'ou.id')
            ->where('comments.article_id', $article_id)
            ->where('comments.pid', 0)
            ->when(Str::isTrue(config('bjyblog.comment_audit')), function ($query) {
                return $query->where('comments.is_audited', 1);
            })
            ->orderBy('created_at', 'desc')
            ->get()
            ->toArray();

        foreach ($data as $k => $v) {
            $data[$k]['content'] = htmlspecialchars_decode($v['content']);

            // 获取二级评论
            $this->child = [];
            $this->getTree($v);

            if (!empty($child = $this->child)) {
                // 按评论时间asc排序
                uasort($child, function ($a, $b) {
                    $prev = $a['created_at'] ?? 0;
                    $next = $b['created_at'] ?? 0;

                    if ($prev == $next) {
                        return 0;
                    }

                    return ($prev < $next) ? -1 : 1;
                });

                if ($child !== []) {
                    foreach ($child as $m => $n) {
                        $pid = $n['pid'] ?? 0;

                        // 获取被评论人id
                        $replyUserId = $this->where('id', $pid)->pluck('socialite_user_id');

                        // 获取被评论人昵称
                        $child[$m]['reply_name'] = SocialiteUser::where([
                            'id' => $replyUserId,
                        ])->value('name');
                    }
                }
            }

            $data[$k]['child'] = $child;
        }

        return $data;
    }

    // 递归获取树状结构
    public function getTree($data)
    {
        $child = $this
            ->select('comments.*', 'ou.name', 'ou.avatar', 'ou.is_admin')
            ->join('socialite_users as ou', 'comments.socialite_user_id', 'ou.id', 'ou.is_admin')
            ->where('comments.pid', $data['id'])
            ->when(Str::isTrue(config('bjyblog.comment_audit')), function ($query) {
                return $query->where('comments.is_audited', 1);
            })
            ->orderBy('created_at', 'desc')
            ->get()
            ->toArray();

        if (!empty($child)) {
            foreach ($child as $k => $v) {
                $v['content']  = htmlspecialchars_decode($v['content']);
                $this->child[] = $v;
                $this->getTree($v);
            }
        }
    }

    public function getLatestComments($number)
    {
        return $this->with(['article', 'socialiteUser'])
            ->when(Str::isTrue(config('bjyblog.comment_audit')), function ($query) {
                return $query->where('is_audited', 1);
            })
            ->whereHas('socialiteUser', function ($query) {
                $query->where('is_admin', 0);
            })
            ->has('article')
            ->orderBy('created_at', 'desc')
            ->limit($number)
            ->get()
            ->each(function ($comment) {
                $comment->sub_content = strip_tags($comment->content);

                if (mb_strlen($comment->sub_content) > 10) {
                    if (config('app.locale') === 'zh-CN') {
                        $comment->sub_content = Str::substr($comment->sub_content, 0, 40);
                    } else {
                        $comment->sub_content = Str::words($comment->sub_content, 10, '');
                    }
                }

                if (config('app.locale') === 'zh-CN') {
                    $comment->article->sub_title = Str::substr($comment->article->title, 0, 20);
                } else {
                    $comment->article->sub_title = Str::words($comment->article->title, 5, '');
                }

                return $comment;
            });
    }
}
